package naga.x.platform2.app.support;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import naga.x.platform2.App;
import naga.x.platform2.app.Channel;
import naga.x.platform2.app.mapper.GameServerMapper;
import naga.x.platform2.app.model.GameServer;
import naga.x.platform2.utils.StringUtils;

@Service
public class GameServerSupport implements InitializingBean {

	@Autowired
	private GameServerMapper mapper;
	
	private List<GameServer> servers/*正式服*/, testServers/*测试服*/;
	private Map<Integer, GameServer> serversMap, testServersMap;
	private Map<Channel, List<GameServer>> serversByChannel;
	
	private List<GameServer> wanbaNewServers; // 玩吧新用户玩家展示列表 20170609
	
	@Override
	public void afterPropertiesSet() throws Exception {
		List<GameServer> servers = mapper.findAll();
		List<GameServer> testServers = mapper.findAllFromTest();
		doInit(servers, testServers);
		Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(new ReloadTask(), 1, 1, TimeUnit.MINUTES);
	}
	
	private void doInit(List<GameServer> serverList, List<GameServer> testServerList) {
		servers = serverList;
		testServers = testServerList;
		serversMap = initMap(serverList, false);
		testServersMap = initMap(testServerList, true);
		serversByChannel = initChannelMap(serverList);
		try {
			wanbaNewServers = initWanbaNewServers(serversByChannel.get(Channel.QQ_WANBA), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-06-09 00:00:00"));
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	private Map<Integer, GameServer> initMap(List<GameServer> list, boolean test) {
		Collections.sort(list);
		Map<Integer, GameServer> map = new LinkedHashMap<Integer, GameServer>();
		for (int i = 0; i < list.size(); i++) {
			GameServer gs = list.get(i);
			gs.setTest(test);
			map.put(gs.getId(), gs);
		}
		return map;
	}
	
	private Map<Channel, List<GameServer>> initChannelMap(List<GameServer> servers) {
		Map<Channel, List<GameServer>> map = new EnumMap<Channel, List<GameServer>>(Channel.class);
		for (int i = 0; i < servers.size(); i++) {
			GameServer gs = servers.get(i);
			Channel[] channels = gs.getChannels();
			if (channels == null || channels.length == 0) {
				channels = Channel.vals();
			}
			for (Channel channel : channels) {
				List<GameServer> list = map.get(channel);
				if (list == null) {
					list = new ArrayList<GameServer>();
					map.put(channel, list);
				}
				list.add(gs);
			}
		}
		return map;
	}
	
	private List<GameServer> initWanbaNewServers(List<GameServer> servers, Date date) {
		if (servers == null) {
			return Collections.emptyList();
		}
		List<GameServer> list = new ArrayList<GameServer>();
		for (int i = 0; i < servers.size(); i++) {
			GameServer gs = servers.get(i);
			if (gs.getTime() != null && gs.getTime().getTime() >= date.getTime()) {
				list.add(gs);
			}
		}
		return list;
	}
	
	public GameServer get(Integer id) {
		if (id == null) {
			return null;
		}
		GameServer gs = serversMap.get(id);
		if (gs == null) {
			gs = testServersMap.get(id);
		}
		return gs;
	}
	
	public List<GameServer> getByChannel(Channel channel) {
		List<GameServer> list = serversByChannel.get(channel);
		return list != null ? list : Collections.emptyList();
	}
	
	public List<GameServer> get(Channel channel, String userId) {
		if (channel == Channel.QQ_WANBA
				&& StringUtils.isNotEmpty(userId)
				&& !App.getInstance().getWanbaOldUsers().contains(userId)) {
			return wanbaNewServers;
		}
		return getByChannel(channel);
	}
	
	public List<GameServer> getServers() {
		return servers;
	}

	public List<GameServer> getTestServers() {
		return testServers;
	}

	public List<GameServer> getAll() {
		List<GameServer> list = new ArrayList<GameServer>(servers.size() + testServers.size());
		list.addAll(testServers);
		list.addAll(servers);
		return list;
	}
	
	private static boolean isDirty(List<GameServer> newestList, Map<Integer, GameServer> oldMap) {
		if (newestList.size() != oldMap.size()) {
			return true;
		}
		for (int i = newestList.size() - 1; i >= 0; i--) {
			GameServer newer = newestList.get(i);
			GameServer older = oldMap.get(newer.getId());
			if (older == null || !newer.equals(older)) {
				return true;
			}
		}
		return false;
	}
	
	class ReloadTask implements Runnable {

		@Override
		public void run() {
			try {
				List<GameServer> serversNewest = mapper.findAll();
				List<GameServer> testServersNewest = mapper.findAllFromTest();
				if (isDirty(serversNewest, serversMap)
						|| isDirty(testServersNewest, testServersMap)) {
					doInit(serversNewest, testServersNewest);
					App.LOG.info("[SERVER LIST RELOAD]OK");
				}
			} catch (Exception e) {
				App.LOG.error("RELOAD SERVER LIST ERROR", e);
			}
		}
		
	}
	
}
